import subprocess
import re

from yacf.Tools.SourceStorage import FileType

class C_FileType(FileType):
    """ A file type to store C source code
    """
    def __init__(self):
        FileType.__init__(self, 'C', '.c')
            
    def pretty_print(self, text):
        """ Return a pretty representation of the file 
        
            :param text: The original text to be pretty printed
        """
        p = subprocess.Popen("indent -kr -", shell=True, bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
        # Send / Retrieve string to the preprocessor
        return p.communicate(text)[0]
    
    def _removeComments(self, string):
        """
            Delete the comments of a given string 
            
            :param string: The original text
        """
        def replacer(match):
            s = match.group(0)
            if s.startswith('/'):
                return ""
            else:
                return s
        pattern = re.compile(
            r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
            re.DOTALL | re.MULTILINE
        )
        return re.sub(pattern, replacer, string)

    def importMacros(self, line_list):
        """ Get the preprocessor macros from a given string
                and store it on the file.


                Currently supported macros are::

                    #include <[A-Za-Z0-9.]+>
                    #include "[A-Za-Z0-9.]+"
        """      
        identifier = "[A-Za-z0-9.-_]+"
        define = '#define ' + identifier
        ifdef = '#if[n]*def ' + identifier
        endif = '#endif'
        _else = '#else'
        include = '#include "' + identifier + '"'
        include_sys = '#include <' + identifier + '>'
        macro_re = re.compile("|".join([include, include_sys]))
        macros = macro_re.findall(self._removeComments(''.join(line_list)))
        return "\n".join(macros)
        # self._files[name + file_type.extension] += "\n".join(macros)
    
class H_FileType(FileType):
    """ A file type to store headers of C source code
    """
    def __init__(self):
        FileType.__init__(self, 'H', '.h')
            
    def pretty_print(self, text):
        """ Return a pretty representation of the file 
        """
        p = subprocess.Popen("indent -kr -", shell=True, bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
        # Send / Retrieve string to the preprocessor
        return p.communicate(text)[0]
    
    def _removeComments(self, string):
        """
            Delete the comments of a given string 
            
            :param string: The original text
        """
        def replacer(match):
            s = match.group(0)
            if s.startswith('/'):
                return ""
            else:
                return s
        pattern = re.compile(
            r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
            re.DOTALL | re.MULTILINE
        )
        return re.sub(pattern, replacer, string)

    def importMacros(self, line_list):
        """ Get the preprocessor macros from a given string
                and store it on the file.


                Currently supported macros are::

                    #include <[A-Za-Z0-9.]+>
                    #include "[A-Za-Z0-9.]+"
        """      
        identifier = "[A-Za-z0-9.-_]+"
        define = '#define ' + identifier
        ifdef = '#if[n]*def ' + identifier
        endif = '#endif'
        _else = '#else'
        include = '#include "' + identifier + '"'
        include_sys = '#include <' + identifier + '>'
        macro_re = re.compile("|".join([include, include_sys]))
        macros = macro_re.findall(self._removeComments(''.join(line_list)))
        return "\n".join(macros)
        # self._files[name + file_type.extension] += "\n".join(macros)
